﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;

namespace PickGold
{
	/// <summary>
	/// 表示同步方法异步操作的状态
	/// </summary>
	/// <typeparam name="RESULT">返回类型</typeparam>
	[Serializable]
	[DataContract]
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	public class SyncResult<RESULT> : MarshalByRefObject, IAsyncResult
	{
		[DataMember]
		private object _AsyncState;
		[DataMember]
		private EventWaitHandle _WaitHandle;
		[DataMember]
		private bool _CompletedSynchronously;
		[DataMember]
		private bool _IsCompleted;

		/// <summary>
		/// 构造一个SyncResult实例
		/// </summary>
		public SyncResult() : this(null, null) { }
		/// <summary>
		/// 构造一个SyncResult实例
		/// </summary>
		/// <param name="handler">调用方法的委托</param>
		public SyncResult(Delegate handler) : this(handler, null) { }
		/// <summary>
		/// 构造一个SyncResult实例
		/// </summary>
		/// <param name="handler">调用方法的委托</param>
		/// <param name="args">参数列表</param>
		public SyncResult(Delegate handler, params object[] args)
		{
			this._AsyncState = null;
			this._WaitHandle = null;
			this._IsCompleted = false;
			this._CompletedSynchronously = true;
			this.Handler = handler;
			this.Args = args;
		}

		/// <summary>
		/// 调用方法的委托
		/// </summary>
		[DataMember]
		public Delegate Handler { set; get; }

		/// <summary>
		/// 调用方法的参数列表
		/// </summary>
		[DataMember]
		public object[] Args { set; get; }

		/// <summary>
		/// 回调方法委托
		/// </summary>
		[DataMember]
		public AsyncCallback Callback { set; get; }

		/// <summary>
		/// 执行所调用的委托结果
		/// </summary>
		[DataMember]
		public RESULT Result { set; get; }

		/// <summary>
		/// 同步执行所调用的方法
		/// </summary>
		/// <returns>委托所表示的方法返回的对象</returns>
		public RESULT Invoke()
		{
			return this.Invoke(this.Args);
		}
		/// <summary>
		/// 同步执行所调用的方法
		/// </summary>
		/// <param name="args">作为参数传递给当前委托所表示的方法的对象数组。- 或 - 如果当前委托所表示的方法不需要参数，则为 null。</param>
		/// <returns>委托所表示的方法返回的对象</returns>
		public RESULT Invoke(params object[] args)
		{
			if (this.Handler == null)
				return this.Result;

			if (this._IsCompleted)
				return this.Result;

			//动态调用（后期绑定）由当前委托所表示的方法。
			this.Result = (RESULT)this.Handler.DynamicInvoke(args);
			this._IsCompleted = true;
			if (!this._CompletedSynchronously)
			{
				if (this._WaitHandle != null)
					this._WaitHandle.Set();
				if (this.Callback != null)
					this.Callback(this);
			}
			return this.Result;
		}

		/// <summary>
		/// 委托调用，如果是同步调用，则在结束调用前无法返回
		/// </summary>
		/// <returns>调用状态，当前对象</returns>
		public IAsyncResult BeginInvoke()
		{
			return this.BeginInvoke(false);
		}
		/// <summary>
		/// 委托调用，如果是同步调用，则在结束调用前无法返回
		/// </summary>
		/// <param name="useThreadPool">是否使用线程池，默认不使用，如果是同步调用则忽略此参数</param>
		/// <returns>调用状态，当前对象</returns>
		public IAsyncResult BeginInvoke(bool useThreadPool)
		{
			if (this._CompletedSynchronously)
			{
				if (this.Callback != null)
					this.Callback(this);
			}
			else if (useThreadPool)
			{
				var wc = new WaitCallback(@object => this.Invoke());
				ThreadPool.QueueUserWorkItem(wc);
			}
			else
			{
				var ts = new ThreadStart(() => this.Invoke());
				new Thread(ts).Start();
			}
			return this;
		}

		/// <summary>
		/// 结束调用，直接调用 Invoke 方法
		/// </summary>
		/// <returns>委托所表示的方法返回的对象</returns>
		public RESULT EndInvoke()
		{
			if (this._IsCompleted)
				return this.Result;

			return this.Invoke();
		}

		#region IAsyncResult 成员

		/// <summary>
		/// 获取或设置用户定义的对象，它限定或包含关于异步操作的信息。
		/// </summary>
		public object AsyncState
		{
			set
			{
				this._AsyncState = value;
			}
			get
			{
				return this._AsyncState;
			}
		}

		/// <summary>
		/// 获取或设置用于等待异步操作完成的 System.Threading.WaitHandle。
		/// </summary>
		public WaitHandle AsyncWaitHandle
		{
			get
			{
				if (this._WaitHandle == null)
					this._WaitHandle = new ManualResetEvent(this.IsCompleted);
				return this._WaitHandle;
			}
		}

		/// <summary>
		/// 获取或设置异步操作是否同步完成的指示。
		/// </summary>
		public bool CompletedSynchronously
		{
			set
			{
				this._CompletedSynchronously = value;
			}
			get
			{
				return this._CompletedSynchronously;
			}
		}

		/// <summary>
		/// 获取或设置异步操作是否已完成的指示。
		/// </summary>
		public bool IsCompleted
		{
			set
			{
				this._IsCompleted = value;
				if (this._WaitHandle == null)
					return;

				if (value)
					this._WaitHandle.Set();
				else
					this._WaitHandle.Reset();
			}
			get
			{
				if (this._CompletedSynchronously)
					return true;

				return this._IsCompleted;
			}
		}

		#endregion

		/// <summary>
		/// 结束调用，直接调用 Invoke 方法
		/// </summary>
		/// <param name="asyncResult">调用状态，【SyncResult】实例，否则返回为空</param>
		/// <returns>委托所表示的方法返回的对象</returns>
		public static RESULT EndInvoke(IAsyncResult asyncResult)
		{
			var sr = asyncResult as SyncResult<RESULT>;
			if (sr == null)
				return default(RESULT);

			return sr.EndInvoke();
		}
	}

	/// <summary>
	/// 表示同步方法异步操作的状态
	/// </summary>
	[Serializable]
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	public class SyncResult : SyncResult<object>
	{
		/// <summary>
		/// 构造一个SyncResult实例
		/// </summary>
		public SyncResult() : base() { }
		/// <summary>
		/// 构造一个SyncResult实例
		/// </summary>
		/// <param name="handler">调用方法的委托</param>
		public SyncResult(Delegate handler) : base(handler) { }
		/// <summary>
		/// 构造一个SyncResult实例
		/// </summary>
		/// <param name="handler">调用方法的委托</param>
		/// <param name="args">参数列表</param>
		public SyncResult(Delegate handler, params object[] args) : base(handler, args) { }
	}
}
